package pub.developers.forum.infrastructure;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.util.ObjectUtils;
import pub.developers.forum.api.response.data.LastMonthData;
import pub.developers.forum.api.response.data.YestData;
import pub.developers.forum.api.response.user.UserInfoResponse;
import pub.developers.forum.common.enums.FollowedTypeEn;
import pub.developers.forum.common.model.PageRequest;
import pub.developers.forum.common.model.PageResult;
import pub.developers.forum.common.support.LogUtil;
import pub.developers.forum.domain.entity.Follow;
import pub.developers.forum.domain.entity.User;
import pub.developers.forum.domain.repository.UserRepository;
import pub.developers.forum.infrastructure.dal.dao.PostsDAO;
import pub.developers.forum.infrastructure.dal.dao.UserDAO;
import pub.developers.forum.infrastructure.dal.dao.UserFollowDAO;
import pub.developers.forum.infrastructure.dal.dataobject.UserDO;
import pub.developers.forum.infrastructure.dal.dataobject.UserFollowDO;
import pub.developers.forum.infrastructure.transfer.UserTransfer;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Slf4j
@Repository
public class UserRepositoryImpl implements UserRepository {

    @Resource
    private UserDAO userDAO;

    @Resource
    private UserFollowDAO userFollowDAO;

    @Resource
    private PostsDAO postsDAO;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;


    @Override
    public PageResult<User> pageFollower(PageRequest<Long> pageRequest) {
        PageHelper.startPage(pageRequest.getPageNo(), pageRequest.getPageSize());
        List<UserFollowDO> userFollowDOS = userFollowDAO.query(UserFollowDO.builder()
                .followedType(FollowedTypeEn.USER.getValue())
                .follower(pageRequest.getFilter())
                .build());

        PageInfo<UserFollowDO> pageInfo = new PageInfo<>(userFollowDOS);

        if (ObjectUtils.isEmpty(userFollowDOS)) {
            return PageResult.build(pageInfo.getTotal(), pageInfo.getSize(), new ArrayList<>());
        }

        List<Long> followedIds = new ArrayList<>();
        userFollowDOS.forEach(followDO -> followedIds.add(followDO.getFollowed()));

        return pageUser(pageInfo, followedIds);
    }

    @Override
    public PageResult<User> pageFans(PageRequest<Long> pageRequest) {
        PageHelper.startPage(pageRequest.getPageNo(), pageRequest.getPageSize());
        List<UserFollowDO> userFollowDOS = userFollowDAO.query(UserFollowDO.builder()
                .followed(pageRequest.getFilter())
                .followedType(FollowedTypeEn.USER.getValue())
                .build());
        PageInfo<UserFollowDO> pageInfo = new PageInfo<>(userFollowDOS);

        if (ObjectUtils.isEmpty(userFollowDOS)) {
            return PageResult.build(pageInfo.getTotal(), pageInfo.getSize(), new ArrayList<>());
        }

        List<Long> followerIds = new ArrayList<>();
        userFollowDOS.forEach(followDO -> followerIds.add(followDO.getFollower()));

        return pageUser(pageInfo, followerIds);
    }

    @Override
    public PageResult<User> pageActive(PageRequest pageRequest) {
        PageHelper.startPage(pageRequest.getPageNo(), pageRequest.getPageSize());
        List<UserDO> userDOS = userDAO.queryOrderLastLoginTime();
        PageInfo<UserDO> pageInfo = new PageInfo<>(userDOS);
        if (ObjectUtils.isEmpty(userDOS)) {
            return PageResult.build(pageInfo.getTotal(), pageInfo.getSize(), new ArrayList<>());
        }

        return PageResult.build(pageInfo.getTotal(), pageInfo.getSize(), UserTransfer.toUsers(userDOS));
    }




    @Override
    public Follow getFollow(Long followed, Long follower) {
        List<UserFollowDO> followDOList = userFollowDAO.query(UserFollowDO.builder()
                .followed(followed)
                .follower(follower)
                .build());
        if (ObjectUtils.isEmpty(followDOList)) {
            return null;
        }

        return UserTransfer.toFollow(followDOList.get(0));
    }

    @Override
    public void follow(Long followed, Long follower) {
        UserFollowDO userFollowDO = UserFollowDO.builder()
                .followed(followed)
                .followedType(FollowedTypeEn.USER.getValue())
                .follower(follower)
                .build();
        userFollowDO.initBase();

        try {
            userFollowDAO.insert(userFollowDO);
        } catch (DuplicateKeyException e) {
            LogUtil.info(log, "唯一键冲突，已存在关注关系，followed={}, follower={}", followed, follower);
        }
    }

    @Override
    public void cancelFollow(Long followId) {
        userFollowDAO.delete(followId);
    }

    @Override
    public User get(Long id) {
        UserDO userDO = userDAO.get(id);

        return UserTransfer.toUser(userDO);
    }

    @Override
    public void save(User user) {
        UserDO userDO = UserTransfer.toUserDO(user);
        userDO.initBase();
        userDAO.insert(userDO);
        user.setId(userDO.getId());
    }


    @Override
    public void delete(Long id) {
        //删除用户的时候,将帖子也删除
        userDAO.delete(id);
        postsDAO.deleteByAuthorId(id);
    }

    @Override
    public User getByEmail(String email) {
        UserDO userDO = userDAO.getByEmail(email);

        return UserTransfer.toUser(userDO);
    }

    public User getByOpenid(String openid){
        UserDO userDO = userDAO.getByOpenid(openid);
        if (userDO == null) {
            return null;
        }
        return UserTransfer.toUser(userDO);
    }

    @Override
    public void update(User user) {

        userDAO.update(UserTransfer.toUserDO(user));
    }

    @Override
    public List<User> queryByIds(List<Long> ids) {
        return UserTransfer.toUsers(userDAO.queryInIds(new HashSet<>(ids)));
    }

    @Override
    public PageResult<User> page(PageRequest<User> pageRequest) {
        PageHelper.startPage(pageRequest.getPageNo(), pageRequest.getPageSize());

        UserDO userDO = UserTransfer.toUserDO(pageRequest.getFilter());
        List<UserDO> userDOList = userDAO.query(userDO);
        PageInfo<UserDO> pageInfo = new PageInfo<>(userDOList);

        if (ObjectUtils.isEmpty(userDOList)) {
            return PageResult.build(pageInfo.getTotal(), pageInfo.getSize(), new ArrayList<>());
        }

        List<Long> uids = new ArrayList<>();
        userDOList.forEach(userDO1 -> uids.add(userDO1.getId()));

        return pageUser(pageInfo, uids);
    }

    private PageResult<User> pageUser(PageInfo pageInfo, List<Long> uids) {
        List<UserDO> userDOS = userDAO.queryInIds(new HashSet<>(uids));
        if (ObjectUtils.isEmpty(userDOS)) {
            return PageResult.build(pageInfo.getTotal(), pageInfo.getSize(), new ArrayList<>());
        }

        // 按 uids 顺序排序
        List<UserDO> userDOList = uids.stream().map(uid -> {
            for (UserDO userDO : userDOS) {
                if (userDO.getId().equals(uid)) {
                    return userDO;
                }
            }
            return null;
        }).collect(Collectors.toList());

        return PageResult.build(pageInfo.getTotal(), pageInfo.getSize(), UserTransfer.toUsers(userDOList));
    }


    //获取当前登录用户的粉丝列表
    @Override
    public List<UserInfoResponse> querySelfFans(Long id) {
        //首先拿到关注当前登录用户粉丝id数组
        Long[] ids =userFollowDAO.querySelfFans(id);
        if (ids.length < 1) {
            return null;
        }
        return userDAO.queryFollowerInformation(Arrays.asList(ids));
    }

    public List<UserInfoResponse> selectSelfFollower(Long id){
        Long[] ids =userFollowDAO.queryFollower(id);
        //////System.out.println(Arrays.toString(ids));
        if(ids.length < 1){
            return null;
        }
        return userDAO.queryFollowerInformation(Arrays.asList(ids));
    }

    //根据用户id 拿到用户昵称
    @Override
    public UserInfoResponse getUserInformation(Long id)
    {
        return userDAO.selectNicknameById(id);
    }

    //将验证码存入到redis数据库中
    @Override
    public void saveCode(String email , String emailCode)
    {
        //设置键值对
        /*
        key:email 接收验证码的邮箱
        value : code 接收到的验证码
         */
        redisTemplate.opsForValue().set(email , emailCode);
        // 设置过期时间为30分钟
        redisTemplate.expire(email, 30, TimeUnit.MINUTES);
    }

    //将验证码从redis数据库中取出
    public String rightCode(String email)
    {
        return (String) redisTemplate.opsForValue().get(email);
    }

    //拿到当前登录用户的信息
    @Override
    public User selfInformation(Long id) {
        return UserTransfer.toUser(userDAO.selectSelfInformation(id));
    }

    //根据当前登录用户的id , 拿到用户的openid (不能返回给前端)
    public String queryOpenId(Long id)
    {
        String openID = userDAO.selectOpenIdById(id);
        if (openID == null)
        {
            return "";
        }
        return openID;
    }


    //拿到我点赞的帖子的id
    @Override
    public PageResult<Long> queryMyLoveId(Long id , Integer pageNo , Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<Long> ids = userFollowDAO.selectMyLovePosts(id);
        PageInfo<Long> pageInfo = new PageInfo<>(ids);
        return PageResult.build(pageInfo.getTotal(), pageInfo.getSize(), ids);
    }

    //统计出昨日的数据
    @Override
    public YestData queryYestDayData() {
        // 获取当前时间
        LocalDateTime currentTime = LocalDateTime.now();
        // 获取昨天的时间
        LocalDateTime yesterday = currentTime.minusDays(1);
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 将当前时间格式化为指定格式
        String formattedDateTimeNow = currentTime.format(formatter);
        String formattedDateTimeYest = yesterday.format(formatter);

        //昨日新增的互动数据
        Long interact = userFollowDAO.selectNewAddFollow(formattedDateTimeYest , formattedDateTimeNow);
        //昨日新增的用户数
        Long newUser = userDAO.selectNewAddUser(formattedDateTimeNow , formattedDateTimeYest);
        //昨日新增的帖子数
        Long newPosts = postsDAO.selectNewPosts(formattedDateTimeNow , formattedDateTimeYest);

        return new YestData(interact , newUser , newPosts);
    }

    //统计近一个月的用户互动数
    @Override
    public List<LastMonthData> queryMonthCount(String type) {
        // 获取当前时间
        LocalDateTime currentTime = LocalDateTime.now();
        // 获取一个月前的时间
        LocalDateTime oneMonthAgo = currentTime.minusMonths(1);
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 将当前时间和一个月前的时间格式化为指定格式
        String formattedDateTimeNow = currentTime.format(formatter);
        String formattedDateTimeOneMonthAgo = oneMonthAgo.format(formatter);
        List<LastMonthData> result = new ArrayList<>();
        if (type.equals("1"))
        {
            //查询近一个月的互动数据
            result = userFollowDAO.selectMonthData(formattedDateTimeOneMonthAgo , formattedDateTimeNow);
        }
        else if (type.equals("2"))
        {
            //查询近一个月的用户数据
            result = userDAO.selectMonthData(formattedDateTimeOneMonthAgo , formattedDateTimeNow);
        }
        else
        {
            //帖子数据
            result = postsDAO.selectMonthData(formattedDateTimeOneMonthAgo , formattedDateTimeNow);
        }
        return result;
    }

    @Override
    public PageResult<UserInfoResponse> queryMyLove(Object userId , Integer pageSize , Integer pageNo) {
        PageHelper.startPage(pageNo , pageSize);
        List<Long> ids =userFollowDAO.myLovePerson((Long) userId);
        PageInfo<Long> pageInfo = new PageInfo<>(ids);
        List<UserInfoResponse> userInfoResponses = new ArrayList<>();
        if(!ids.isEmpty()){
            userInfoResponses = userDAO.queryFollowerInformation(ids);
            //查询这些人是否关注我了
            for (UserInfoResponse userInfo : userInfoResponses) {
                if (userFollowDAO.followedMy((Long) userId, userInfo.getId()) == null) {
                    userInfo.setIsLike(false);
                } else {
                    userInfo.setIsLike(true);
                }
            }
        }
        return PageResult.build(pageInfo.getTotal() , pageInfo.getSize() , userInfoResponses);
    }



}
